package cn.easyutil.veteran.web.handler;

import cn.easyutil.veteran.core.utils.SpringUtils;
import cn.easyutil.veteran.web.advice.BeforeResponseAdvice;
import cn.easyutil.veteran.web.provider.DefaultBeforeResponseAdvice;
import cn.easyutil.veteran.web.session.SessionOperation;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import java.lang.reflect.Method;
import java.util.*;

/**
 * 接口数据响应前处理
 */
@RestControllerAdvice
public class BeforeResponseHandle implements ResponseBodyAdvice {

    private BeforeResponseAdvice beforeResponseAdvice;

    private final BeforeResponseAdvice defaultAdvice = new DefaultBeforeResponseAdvice();

    @Override
    public boolean supports(MethodParameter returnType, Class converterType) {
        return getAdvice().supports(returnType, converterType);
    }

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        Method method = Objects.requireNonNull(returnType.getMethod());
        if(SessionOperation.toPackage.get()){
            body = getAdvice().toPackage(body, method);
        }
        SessionOperation.responseParams.set(body);
        Object result = body;
        if(SessionOperation.toSecret.get()){
            result = getAdvice().toSecret(body,method);
        }
        return getAdvice().beforeBodyWrite(result,method);
    }

    private BeforeResponseAdvice getAdvice(){
        if(this.beforeResponseAdvice != null){
            return this.beforeResponseAdvice;
        }
        BeforeResponseAdvice beforeResponseAdvice = SpringUtils.getBean(BeforeResponseAdvice.class);
        if(beforeResponseAdvice == null){
            return defaultAdvice;
        }
        this.beforeResponseAdvice = beforeResponseAdvice;
        return this.beforeResponseAdvice;
    }
}
